﻿using System;
using System.IO;
using System.Threading;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Channels;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using System.Collections.Generic;

using SBPweb.PROvibe.Server.Framework.Actors.Communication;

namespace SBPweb.PROvibe.Server.Framework.Communication
{

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    public class ServerChannel : IServerChannel, ICommunicationChannel
    {

        #region Protected fields

        private const string ChannelNamespace = "SBPweb.PROvibe.Server/IServerChannel/SendMessage";
        protected IClientChannel client = null;
        protected Timer timer = null;
        protected int timerInterval = 10000;
        protected int timerIntervalThreshold = 1000;
        protected Random rnd = new Random();

        #endregion

        #region Constructor logic

        public ServerChannel()
        {
            PollingDuplexServiceHost<IServerChannel, ServerChannel> shb = (PollingDuplexServiceHost<IServerChannel, ServerChannel>)OperationContext.Current.Host;
            timerInterval = (int)shb.OpenTimeout.TotalMilliseconds / 2;
            shb.OnChannelOpened(this);
        }

        #endregion

        #region Methods

        public void SendMessage(Message receivedMessage)
        {
            client = OperationContext.Current.GetCallbackChannel<IClientChannel>();
            SendKeepAlive();
            timer = new Timer(new TimerCallback(OnTimerCallback), null, GetInterval(), Timeout.Infinite);
        }

        public void SendKeepAlive()
        {
            SendMessageBody(KeepAliveContent.CreateMessageBody());
        }

        public void SendInitializeLayout()
        {
            SendMessageBody(InitializeLayoutContent.CreateMessageBody());
        }
        
        private void OnTimerCallback(object data)
        {
            SendKeepAlive();
            timer.Change(GetInterval(), Timeout.Infinite);
        }

        private int GetInterval()
        {
            return rnd.Next(timerInterval - timerIntervalThreshold, timerInterval + timerIntervalThreshold);
        }

        private void SendMessageBody(MessageBody body)
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(MessageBody), MessageContentBase.DataContactTypes);
            Message message = Message.CreateMessage(MessageVersion.Soap11, ChannelNamespace, body, serializer);
            client.SendMessage(message);
        }

        #endregion
        
    }

}